syntax gather take
Documentation for syntax gather take assembled from the following types:
language documentation Control flow
From Control flow
(Control flow) control flow gather take gather take
gather is a statement or block prefix that returns a sequence of values. The values come from calls to take in the dynamic scope of the gather block. In the following example, we implement a subroutine to compute the factors of an integer with gather (note that the factors are not generated in a strictly increasing order):
sub factors( Int:D \n ) {
my $k = 1;
gather {
while $k**2 < n {
if n %% $k {
take $k;
take n div $k;
}
$k++;
}
take $k if $k**2 == n;
}
}
say factors(36); # OUTPUT: «1, 36, 2, 18, 3, 12, 4, 9, 6»
The gather/take combination can generate values lazily, depending on context. If you want to force lazy evaluation use the lazy subroutine or method. Binding to a scalar or sigilless container will also force laziness. For example:
my @vals = lazy gather {
take 1;
say "Produced a value";
take 2;
}
say @vals[0];
say 'between consumption of two values';
say @vals[1];
# OUTPUT:
# 1
# between consumption of two values
# Produced a value
# 2
gather/take is scoped dynamically, so you can call take from subs or methods that are called from within gather:
sub weird(@elems, :$direction = 'forward') {
my %direction = (
forward => sub { take $_ for @elems },
backward => sub { take $_ for @elems.reverse },
random => sub { take $_ for @elems.pick(*) },
);
return gather %direction{$direction}();
}
say weird(<a b c>, :direction<backward> ); # OUTPUT: «(c b a)»
If values need to be mutable on the caller side, use take-rw.
Note that gather/take also work for hashes. The return value is still a Seq but the assignment to a hash in the following example makes it a hash.
my %h = gather { take "foo" => 1; take "bar" => 2};
say %h; # OUTPUT: «{bar => 2, foo => 1}»